Skip to content

feat(alerts): record insight alert investigations for platform evaluations - #123622

Merged
trunk-io[bot] merged 7 commits into
masterfrom
jimmy/insight-alert-investigation
Oct 27, 2026
Merged

trunk-io[bot] merged 7 commits into
masterfrom
jimmy/insight-alert-investigation

Conversation

@jzhu13

@jzhu13 jzhu13 commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Problem

  • Insight alerts with the investigation agent on cannot move to the shared alerts platform yet, because the agent's budget, cooldown and verdict all live on AlertCheck.
  • The platform never writes AlertCheck, so a platform-evaluated alert has nowhere to record an investigation or read the last one.
  • This is the investigation store for that move. Nothing calls it yet; the agent and the platform adapter follow in later layers.

Changes

  • New InsightAlertInvestigation table: one row per platform evaluation that asked for an investigation, keyed on the platform configuration and evaluation key.
  • An episode is one firing, named by the platform's episode_started_at, instead of a run of FIRING AlertCheck rows.
  • products/alerts/backend/platform_investigation.py ports the decision and the claim to the new table:
    • decide_investigation is a read, so a retried evaluation can repeat it. It ignores the evaluation's own row.
    • claim_investigation writes PENDING or SKIPPED under a per-alert advisory lock. A repeated claim returns the first answer, so a retry starts the same agent.
  • The eligibility check, the per-episode budget and the in-flight/cooldown rule move into shared helpers in posthog/temporal/alerts/investigation.py. Both stacks call them, so the rules cannot drift during the parallel run.
  • The firing that is already open when the platform takes an alert over has no recorded start. Its rows share a null episode_started_at and count as one episode.
  • The reverse relation from the new table onto AlertConfiguration is hidden (related_name="+"). With a visible one, code that saves an alert outside a team scope raises TeamScopeError.
  • Nothing user-visible changes.

How did you test this code?

Test rationale:

  • test_platform_investigation.py covers what is new: the episode keying and own-row exclusion on the decision, the claim writing PENDING or SKIPPED through the shared refusal rule, and the repeated claim returning its first answer.
  • The legacy tests in posthog/temporal/tests/test_alerts_investigation.py keep covering the shared rules in full, so the platform tests carry only the wiring cases.
  • Ran locally: the new tests, test_alerts_investigation.py, test_alerts_activities.py, and the full products/alerts suite. Three products/alerts API tests that read platform history fail locally because the local ClickHouse test schema predates the source_detail column on master. CI runs them against a fresh schema.

Release status

  • No feature flag controls this change

Docs update

None. Nothing calls the new code yet.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Claude Code, Claude Opus 5.5

  • Layer I3 of the plan for moving investigating insight alerts onto the alerts platform. It is independent of the delivery-hold layer (I2); the agent and adapter layers stack on both.
  • Skills: /django-migrations, /writing-tests, /code-review high --fix, /simplify, /reviewing-with-coderabbit, /writing-pr-descriptions.
  • /code-review caught that the decision compared platform state names against the insight stack's casing; it now takes firing: bool. Running the legacy tests caught the reverse-relation TeamScopeError.
  • /simplify moved the rules into shared helpers and trimmed the duplicated test cases. Not taken: one table for both stacks, because the platform does not write insight-stack rows.
  • CodeRabbit CLI, --deep: no findings.
  • No duplicate: an open-PR search for investigation work found only an unrelated presentation change.

…tions

The platform never writes AlertCheck, so an investigation of a platform
evaluation needs its own row. InsightAlertInvestigation holds it, and the
budget, carried verdict and claim rules are ported to read it, keyed on
the platform configuration and its firing's start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jzhu13 jzhu13 self-assigned this Oct 26, 2026
@trunk-io

trunk-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

😎 Stack merged successfully - details.

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

This PR is assigned to the backend Python lane. It runs backend Python tests and may merge in parallel with PRs in other lanes.

✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

⚠️ Comment density — 4% of added code lines are comments (13 of 310)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
products/alerts/backend/models/investigation.py 8 59
products/alerts/backend/platform_investigation.py 3 91
products/alerts/backend/tests/test_platform_investigation.py 2 133

This check does not block merging. It updates on every push and clears when the share drops.

⚠️ Django migration SQL — 1 new migration to review

We've detected new migrations on this PR. Review the SQL output for each migration:

products/alerts/backend/migrations/0015_insight_alert_investigation.py

/home/runner/work/tmp/tool_cache/Python/3.14.7/x64/lib/python3.14/site-packages/anyio/from_thread.py:119: SyntaxWarning: 'return' in a 'finally' block
  return result
2026-10-27T04:47:52.414510Z [error    ] Path must be a valid database or directory containing databases. [posthog.exceptions_capture] pid=28963 tid=139632606714752
Traceback (most recent call last):
  File "/home/runner/work/posthog/posthog/posthog/geoip.py", line 15, in <module>
    geoip: Optional[GeoIP2] = GeoIP2(cache=8)
                              ~~~~~~^^^^^^^^^
  File "/home/runner/work/tmp/tool_cache/Python/3.14.7/x64/lib/python3.14/site-packages/django/contrib/gis/geoip2.py", line 116, in __init__
    raise GeoIP2Exception(
        "Path must be a valid database or directory containing databases."
    )
django.contrib.gis.geoip2.GeoIP2Exception: Path must be a valid database or directory containing databases.
/home/runner/work/tmp/tool_cache/Python/3.14.7/x64/lib/python3.14/site-packages/sshtunnel.py:1040: SyntaxWarning: 'return' in a 'finally' block
  return (ssh_host,
/home/runner/work/tmp/tool_cache/Python/3.14.7/x64/lib/python3.14/site-packages/langchain_core/_api/deprecation.py:27: UserWarning: Core Pydantic V1 functionality isn't compatible with Python 3.14 or greater.
  from pydantic.v1.fields import FieldInfo as FieldInfoV1
System check identified some issues:

WARNINGS:
?: (axes.W001) You are using the django-axes cache handler for login attempt tracking. Your cache configuration is however invalid and will not work correctly with django-axes. This can leave security holes in your login systems as attempts are not tracked correctly. Reconfigure settings.AXES_CACHE and settings.CACHES per django-axes configuration documentation.
?: (staticfiles.W004) The directory '/home/runner/work/posthog/posthog/frontend/dist' in the STATICFILES_DIRS setting does not exist.
BEGIN;
--
-- Create model InsightAlertInvestigation
--
CREATE TABLE "alerts_insightalertinvestigation" ("id" uuid NOT NULL PRIMARY KEY, "configuration_id" uuid NOT NULL, "evaluation_key" varchar(255) NOT NULL, "episode_started_at" timestamp with time zone NULL, "kind" varchar(16) NOT NULL, "status" varchar(10) NOT NULL, "verdict" varchar(20) NULL, "summary" text NULL, "error" jsonb NULL, "evaluated" jsonb NOT NULL, "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "alert_configuration_id" uuid NOT NULL, "notebook_id" uuid NULL, "team_id" integer NOT NULL, CONSTRAINT "insight_alert_investigation_one_per_evaluation" UNIQUE ("configuration_id", "evaluation_key"));
ALTER TABLE "alerts_insightalertinvestigation" ADD CONSTRAINT "alerts_insightalerti_alert_configuration__f6888e9c_fk_posthog_a" FOREIGN KEY ("alert_configuration_id") REFERENCES "posthog_alertconfiguration" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "alerts_insightalertinvesti_alert_configuration_id_f6888e9c" ON "alerts_insightalertinvestigation" ("alert_configuration_id");
CREATE INDEX "alerts_insightalertinvestigation_team_id_ebd9673a" ON "alerts_insightalertinvestigation" ("team_id");
CREATE INDEX "insight_alert_inv_episode_idx" ON "alerts_insightalertinvestigation" ("configuration_id", "episode_started_at", "created_at");
CREATE INDEX "insight_alert_inv_notebook_idx" ON "alerts_insightalertinvestigation" ("notebook_id") WHERE "notebook_id" IS NOT NULL;
CREATE INDEX "insight_alert_inv_recent_idx" ON "alerts_insightalertinvestigation" ("configuration_id", "created_at");
COMMIT;

Last updated: 2026-10-27 04:48 UTC (4673a22)

✅ Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 1 Safe | 0 Needs Review | 0 Blocked

✅ Safe

Brief or no lock, backwards compatible

alerts.0015_insight_alert_investigation
  └─ #1 ✅ CreateModel
     Creating new table is safe
     model: InsightAlertInvestigation
  │
  └──> ℹ️  INFO:
       ℹ️  Skipped operations on newly created tables (empty tables
       don't cause lock contention).

Last updated: 2026-10-27 04:48 UTC (4673a22)

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostHog Review · Standard · reviewed e75437a: 1 Should fix.

This is the only automatic review while this pull request is a draft. Comment @posthog review to review new changes sooner. Otherwise, a review of the new changes runs when you mark it ready for review.

See this review and its findings in PostHog Review. Comment @posthog review --deep for a Deep review. A Deep review takes longer and looks deeper than a Standard review.

…link

Add InsightAlertInvestigation to the IDOR semgrep rules, declare the test
class attributes for mypy, and index the notebook link (non-null rows
only) so deleting a notebook does not scan the table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@jzhu13
jzhu13 marked this pull request as ready for review October 26, 2026 20:31
@parameterai

parameterai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Risk: No findings

Since the last review the only authored change is a merge commit's edit to the semgrep IDOR model lists: InsightAlertInvestigation is now listed (alphabetically) in the two team-scoping enforcement rules, and SignalReportMonitoringResult entries that an earlier branch commit had dropped are restored. Both classifications match the actual model definitions, and no model was removed from any enforcement list, so the security rules are strengthened, not weakened.

Sentinel reviewed accca4e · Review settings

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team October 26, 2026 20:32
@jzhu13 jzhu13 added the stamphog Request AI approval (no full review) label Oct 26, 2026
stamphog[bot]

This comment was marked as outdated.

@jzhu13

jzhu13 commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

jzhu13 and others added 2 commits October 26, 2026 15:50
…e hold model's

Both this PR and the delivery-hold PR inserted a line at the same spot in
the IDOR model lists, so whichever landed second conflicted. List the
investigation model next to AlertConfiguration instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@stamphog
stamphog Bot dismissed their stale review October 26, 2026 22:51

A new stamphog review started for this PR — the fresh verdict replaces this approval.

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not approved yet — waiting on the conditions below.

The Migration risk check has not finished for this commit, so stamphog cannot tell a safe migration from a risky one yet. The review runs again on the next push, or you can re-request it once the check reports.

Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✗ matches: migrations
size ✓ 358L, 7F substantive, 516L/9F incl. docs/generated/snapshots — within ceiling
tier ✗ classified as T2-never: T2-never (516L, 9F, cross-cutting, feat)
stamphog 2.6.1 .stamphog/policy.yml @ unknown · reviewed head accca4e

@jzhu13 jzhu13 added stamphog Request AI approval (no full review) and removed stamphog Request AI approval (no full review) labels Oct 27, 2026
stamphog[bot]

This comment was marked as outdated.

@jzhu13

jzhu13 commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jzhu13

jzhu13 commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

/trunk cancel

@jzhu13
jzhu13 changed the base branch from master to jimmy/insight-alert-investigation-idor-rule October 27, 2026 03:16
@stamphog
stamphog Bot dismissed their stale review October 27, 2026 03:16

The PR was retargeted to a different base branch, so the approved diff is no longer what was reviewed. Stamphog re-reviews automatically.

stamphog[bot]

This comment was marked as outdated.

@stamphog
stamphog Bot dismissed their stale review October 27, 2026 03:17

A new stamphog review started for this PR — the fresh verdict replaces this approval.

@jzhu13
jzhu13 added this pull request to stack #123780 October 27, 2026 03:17

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not approved yet — waiting on the conditions below.

The Migration risk check has not finished for this commit, so stamphog cannot tell a safe migration from a risky one yet. The review runs again on the next push, or you can re-request it once the check reports.

Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✗ matches: migrations
size ✓ 356L, 6F substantive, 514L/8F incl. docs/generated/snapshots — within ceiling
tier ✗ classified as T2-never: T2-never (514L, 8F, two-areas, feat)
stamphog 2.6.1 .stamphog/policy.yml @ unknown · reviewed head 7951940

@jzhu13 jzhu13 added stamphog Request AI approval (no full review) and removed stamphog Request AI approval (no full review) labels Oct 27, 2026
stamphog[bot]

This comment was marked as outdated.

Base automatically changed from jimmy/insight-alert-investigation-idor-rule to master October 27, 2026 04:26
@stamphog
stamphog Bot dismissed their stale review October 27, 2026 04:26

The PR was retargeted to a different base branch, so the approved diff is no longer what was reviewed. Stamphog re-reviews automatically.

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not approved yet — waiting on the conditions below.

The Migration risk check has not finished for this commit, so stamphog cannot tell a safe migration from a risky one yet. The review runs again on the next push, or you can re-request it once the check reports.

Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✗ matches: migrations
size ✓ 356L, 6F substantive, 514L/8F incl. docs/generated/snapshots — within ceiling
tier ✗ classified as T2-never: T2-never (514L, 8F, two-areas, feat)
stamphog 2.6.1 .stamphog/policy.yml @ unknown · reviewed head 4673a22

@jzhu13 jzhu13 added stamphog Request AI approval (no full review) and removed stamphog Request AI approval (no full review) labels Oct 27, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

The change enters schema, model, and write-path territory, with owning-team authorship providing an assurance path. No current-head review is provided; the older bot review names no concrete concern to verify, and the code shows no identified showstopper.

  • Author wrote 0% of the modified lines and has 24 merged PRs in these paths (familiarity MODERATE).
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 356L, 6F substantive, 514L/8F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (514L, 8F, two-areas, feat)
stamphog 2.6.1 .stamphog/policy.yml @ 4673a22 · reviewed head 4673a22

@jzhu13

jzhu13 commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

@trunk-io
trunk-io Bot merged commit 9c16efd into master Oct 27, 2026
275 checks passed
@trunk-io
trunk-io Bot deleted the jimmy/insight-alert-investigation branch October 27, 2026 05:18
@deployment-status-posthog

deployment-status-posthog Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-27 05:54 UTC Run
prod-us ✅ Deployed 2026-10-27 06:11 UTC Run
prod-eu ✅ Deployed 2026-10-27 06:17 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant